package lamerman.lib.filesystem.rms;

import java.util.Enumeration;
import java.util.Hashtable;
import lamerman.lib.filesystem.rms.misc.Cluster;

public class RMSFSDir extends RMSFSNode {

    private Hashtable hNodes = new Hashtable();

    public RMSFSDir(RMSFSDir argParent, String argName, RMSFSBase argRmsFsBase) {
        super(argParent, argName, argRmsFsBase);

    }

    public final RMSFSFile makeFile(String argName, byte[] argBytes) throws RMSFSException, IllegalArgumentException, RMSFSFatalException {
        synchronized (rmsFsBase) {
            if (argName == null || argName.length() == 0) {
                throw new IllegalArgumentException("Illegal file name");
            }
            if (argBytes == null || argBytes.length == 0) {
                throw new IllegalArgumentException("Can't create a file with the lenght 0");
            }
            if (hNodes.get(argName) != null) {
                throw new RMSFSException("File with this name already exist");
            }

            RMSFSFile file = new RMSFSFile(this, argName, argBytes);
            hNodes.put(file.name, file);

            return file;
        }
    }

    final RMSFSFile makeFile(String argName, Cluster[] argClusters, int argLength) throws RMSFSException, IllegalArgumentException, RMSFSFatalException {
        synchronized (rmsFsBase) {
            if (argName == null || argName.length() == 0) {
                throw new IllegalArgumentException("Illegal file name");
            }
            if (hNodes.get(argName) != null) {
                throw new RMSFSException("Node with the name " + argName + " already exist");
            }

            RMSFSFile file = new RMSFSFile(this, argName, argClusters, argLength);
            hNodes.put(file.name, file);

            return file;
        }
    }

    public final RMSFSDir makeDir(String argName) throws RMSFSException {
        synchronized (rmsFsBase) {
            if (argName == null || argName.length() == 0) {
                throw new IllegalArgumentException("Illegal directory name");
            }
            if (hNodes.get(argName) != null) {
                throw new RMSFSException("Node with the name " + argName + " already exist");
            }

            RMSFSDir dir = new RMSFSDir(this, argName, rmsFsBase);
            hNodes.put(dir.name, dir);

            return dir;
        }
    }

    public final RMSFSNode getNode(String argName) throws RMSFSException, IllegalArgumentException {
        synchronized (rmsFsBase) {
            if (argName == null || argName.length() == 0) {
                throw new IllegalArgumentException("Illegal file name");
            }

            RMSFSNode node = (RMSFSNode) hNodes.get(argName);
            if (node == null) {
                throw new RMSFSException("Node with such name does not exist");
            }

            return node;
        }
    }

    public final void deleteNode(String argName) throws RMSFSException, RMSFSFatalException {
        synchronized (rmsFsBase) {
            if (argName == null) {
                throw new IllegalArgumentException("Illegal file name");
            }

            RMSFSNode node = (RMSFSNode) hNodes.get(argName);
            if (node == null) {
                throw new RMSFSException("File with such name does not exist");
            }

            deleteNode(node);
        }
    }

    public final void deleteNode(RMSFSNode argNode) throws RMSFSException, RMSFSFatalException {
        synchronized (rmsFsBase) {
            if (argNode == null) {
                throw new IllegalArgumentException("Node is null");
            }

            //if it's a file, just delete it
            if (argNode instanceof RMSFSFile) {
                rmsFsBase.deallocateSpace(((RMSFSFile) argNode).aClusters);

                //else if it's a directory, delete all it's files and directories first
            } else if (argNode instanceof RMSFSDir) {
                RMSFSDir dir = (RMSFSDir) argNode;
                RMSFSNode[] aNodes = ((RMSFSDir) argNode).listNodes();
                for (int nID = 0; nID < aNodes.length; nID++) {
                    RMSFSNode node = aNodes[nID];
                    dir.deleteNode(node);
                }
            }

            hNodes.remove(argNode.name);
        }
    }

    public final RMSFSNode[] listNodes() {
        synchronized (rmsFsBase) {
            RMSFSNode[] result = new RMSFSNode[hNodes.size()];
            Enumeration en = hNodes.elements();

            int i = 0;
            while (en.hasMoreElements()) {
                result[i++] = (RMSFSNode) en.nextElement();
            }

            return result;
        }
    }

    public final boolean isDirectory() {
        return true;
    }
}
